\name{connect}
\alias{connectBefore.default}
\alias{connectAfter.default}
\alias{connectAround.default}
\alias{modifyResults.default}
\alias{removeConnects.default}

\title{ Connect functions }
\description{
  Create AOP-style connections between functions. These are the core
  connection creating functions that form the heart of the
  aspect-oriented programming. 
}      
\usage{
\method{connectBefore}{default}(fun, newFun, env = parent.frame(), ...,
              connectGlobally = !funExistsInEnv)
\method{connectAfter}{default}(fun, newFun, env = parent.frame(), ...,
              connectGlobally = !funExistsInEnv)
\method{connectAround}{default}(fun, newFun, env = parent.frame(), ...,
              connectGlobally = !funExistsInEnv)
\method{modifyResults}{default}(fun, newFun, env = parent.frame(), ...,
              connectGlobally = !funExistsInEnv)

\method{removeConnects}{default}(fun, newFun = NULL, env = parent.frame(), ...,
              connectGlobally = !funExistsInEnv)
}
\arguments{
  \item{fun}{ the function modified by the connection. It may be a name
    or function variable. This function is copied to \code{origFun},
    which can be called inside of \code{newFun}.}
  \item{newFun}{ the function connected to. It may or may not have the
    same arguments as fun.}
  \item{env}{ the environment where to make the connection, defaulting
    to the environment of the calling function. }
  \item{connectGlobally}{ a logical that if TRUE will look through the search
    list to replace all versions (including namespaced versions) of the function.}
  \item{...}{ additional parameters are passed to \code{otherArgs} for
    use inside of newFun.}
}
\details{

These connector functions link up the actions of two functions. This is
a simplified form of aspect-oriented programming (AOP). The main feature
of this style of programming is after-the-fact connecting together of
functionality.

Connections work by replacing a function with another function
and using environments to store previous versions of functions.
So, connectBefore(f1, f2) replaces f1 with function(...) {f2(...); f1(...)},
and f1 is stored in the environment of the new function. Replacement is
done using the assignment operator ("<-"), not with \code{assign}, so it
is possible to specify \code{fun} as \code{lst$fun1} or \code{arry[2]}.

The default for these connection functions is that if the function
exists in the calling environment, then only that function is
replaced. If the function does not exist in the calling environment,
then the search path is searched to replace all versions of the
function. Internally, this uses a copy of \code{fun.locator} from Mark
Bravington's debug package.

\code{connectAround} is the most versatile type of
"advice". Effectively, the original function (\code{fun}) is replaced by
\code{newFun}. \code{newFun} can in turn call \code{origFun}. Note,
\code{origFun} must be used, not \code{fun}, or you'll end up with an
endless recursion. \code{connectAround} can be used to replace
functions. This can be used as an alternative to
\code{assignInNamespace}. The main difference is that
\code{connectAround} replaces all versions of the function, not just the
version in the namespace. This includes other copies in the search
path and copies imported into other namespaces.

\code{removeConnects} removes connections, either individually or all of
them. The call to removeConnects should have the same form as the call
to the connector function that initiated the connection. 

}
\value{
  None. All of the functions are run for their side effects.
}
\references{ 
  \url{http://en.wikipedia.org/wiki/Aspect-oriented_programming}
}
\author{ Tom Short }
\seealso{ \code{\link{makeConnector}}
}
\examples{
  f1 = function(a,b) cat("F1 (A+B):", a+b, "\n")
  f2 = function(a,b) cat("F2 (A-B):", a-b, "\n")
  f3 = function(a,b) cat("F3 (A*B):", a*b, "\n")
  f1(5,3)
  connectBefore(f1, f2)
  f1(5,3)
  connectAfter(f1, f3)
  connectAfter(f1, function(a,b) cat("F4 (A/B):", a/b, "\n"))
  f1(5,3)
  f1
  removeConnects(f1, f2)
  removeConnects(f1, function(a,b) cat("F4 (A/B):", a/b, "\n"))
  f1(5,3)
  f1  # should be just f3 left connected

  # now, try connecting to plot in the namespace:graphics
  p <- function(...) cat("plotting...\n")
  p2 <- function(...) cat("plotting...2\n")
  connectBefore(plot, p)
  connectBefore(plot, function(...) cat("plotting...3\n"))
  plot(sin) 
  removeConnects(plot)
  removeConnects(plot, function(...) cat("plotting...3\n"))
  plot(1:10)
  
  # try it on some methods:
  df <- data.frame(a=1, b=2)
  connectBefore("$<-.data.frame", function(...) cat("accessing DF:\n"))
  df$c <- 5
  removeConnects("$<-.data.frame")
  
  connectBefore(plot.default, function(...) cat("accessing DF:\n"))
  plot(cos)
  removeConnects(plot.default)
  plot(sin)

  # try functions in list elements
  lst <- list(a = 1, b = function() cat("b:\n"))
  connectBefore(lst$b, function() cat("a:"))
  lst$b()
  removeConnects(lst$b)
  lst$b()

  # try it with proto environments (one of R's OOP styles)
  if (require(proto)) {
    b <- function() cat("b\n")
    p <- proto(expr = {
      x <- 1
      y <- 2
      ff <- function(., x, y) x + y
      plot <- function(.) cat("hello\n")
    })
    ## this don't work right:
    # connectBefore(p$ff, function(...) cat("p\n"))
    ## this should:
    with(p, connectBefore(ff, function(...) cat("ff\n")))
    p$ff(1,2)
    p[["ff"]]
    with(p, connectBefore(plot, function(...) cat("ff")))
    p$plot()
    plot(1) # shouldn't be affected
  }

  connectAround(median, mean) # replace the median with mean
  median(c(1:5, 50000)) 
  removeConnects(median)
  median(c(1:5, 50000))
}
\keyword{ programming }
\keyword{ methods }
